* iBook 800 MHz G3 with firmware patch to allow screen spanning.
* HP 2159m 1920x1080 LCD connected via VGA.
* Want to drive it at 1920x1080.
* Doesn't show that resolution in Monitors.
* Highest shown is 1792x1344 resolution that does have a high pixel
rate.


Finding timing values
---------------------
* Tried DMSetDisplayMode scanning codes, codes in Video.h, but doesn't
have any presets.
* Tried SwitchRes 2.5.3. Didn't help. Doesn't allow defining custom
timings.
* Set breakpoint on DMSetDisplayMode and stepped in a while, but too
much happening to find where it sets resolution.
* Noticed some timing structures in Video.h, VDDisplayTimingRangeRec and
VDDetailedTimingRec, and some Control/Status codes to use with these.
Tried them. The range one seemed to work for one of the displays, but I
could never set the timing.
* Resorted to scanning memory for values that looked like resolutions.
Had it scan for say 1792, then when found, scan nearby for 1344, etc.
Eventually found resolution values that when changed changed what was
shown in Monitors.
* Found resolutions had display res, then a higher value, suggesting
these were the timings. Modified them and got a new resolution!
* Pixel timing was same as old mode (using 1792x1344 as base) , so this
one's frame rate went from 60 to 72 Hz.


Timing format
-------------
* Found pixel clock in word just before H resolution. It's simply clock
rate in Hz / 10000. So it expresses rate in MHz to 1/100 precision, e.g.
148.55 MHz is stored as 14855.
* Format is words. polarity clock hres htotal hsync syncwidth vres
vtotal vsync vfront.
* sync begins hsync dots after active ends
* sync width is syncwidth
* active begins htotal-hres dots after previous active ends, thus
sync+syncwidth must be somewhat less than htotal-hres or colors show up
wrong
* widths are all in dots
* polarities: 0200 -hsync +vsync; 0100 +hsync -vsync  etc.
* Put in some standard resolution timing values and measured with
frequency meter and the htotal, vtotal, and clock values were what was
expected.


Patching driver
---------------
* Have done this before with PowerMac 8500 built-in driver. Timings are
probably stored in globals of a code fragment, which uses mild
compression on disk, thus we can't just search for what we see in
memory.
* Looked for some more unique long values. 4FFB0700 was a decent one.
* Scanned for this in memory. Noted general places found.
* Removed some ATI-related extensions, restarted, then scanned memory
again.
* Narrowed down to ATI Driver Update; this one caused that to appear in
memory, so the timings were in it somewhere.
* I have some code that loads a fragment (so that the system
decompresses them), then writes its globals. I ran it on this file, but
had 33 freaking fragments, so I had to modify it to scan them all.
Complicated by cfgr appearing corrupt in Resorcerer, so I had to
manually find fragments. Some errors on some, just forged on.
* Scanned dumps of globals for 4FFB0700 and found a few. But the overall
data didn't match what I was seeing in memory, so I figured that it was
translating the data somehow in memory, ugh.
* Resorted to a simpler strategy; find occurrences of 4FFB in compressed
globals in fragments on disk, change them to 4BE0, 4BE1, etc., restart,
and then see which ones I find in memory, modify them, find which is
related to actual resolution, then I know which one.
* Did this, and found that only one of them was the cause of several
copies in memory. This was the one. So now I just had to modify the
globals in the fragment on disk.
* I found that they were very inefficiently represented. For example,
the 4FFB0700 was represented as 23 4F FB 07 01, which means 3 unencoded
bytes (23), those bytes, then one zero byte (01). This uses more bytes
than just a straight run, but it meant that I definitely had enough room
to modify the record.
* The resolution was found at 2B7088:

2B7088: 02 01 23 4F FB 07 01 22 09 90 01 21 80 01 25 C8 05 40
05 72 01 21 01 01 21 03 04

(decompressed: 0200 4FFB 0700 0990 0080 00C8 0540
0572 0001 0003 0000 0000)

* The challenge became keeping my data taking a lot of space rather than
doing it more efficiently. I ended up encoding it as several four-byte
runs, with a zero run at the end to match up with the old. I changed it
to

2B7088: 02 01 24 35 F0 07 80 24 07 D0 00 08 24 00 10 04 38 24
04 57 00 03 23 00 08 00 03 

(decompressed: 0200 35F0 0780 07D0 0008 0010 0438
0457 0003 0008 0000 0000)


Adjusting timing without restarting
-----------------------------------
* In macsbug, execute
db 0
f .+1 100000 35F00780
f .+1 100000 35F00780
f .+1 100000 35F00780
* This finds the third occurrence. Now, make a note of the address.
Then, do
sw <address> 35F0 0780 07D0 ...

putting the new values you want.
* Resume execution, then in monitors (can keep it open through all
this), switch to another resolution, then back to the new one (which can
be totally changed; new pixel size, clock, etc.). You can use arrow keys
to switch resolutions, just hit up then down to toggle to another then
same one.



HP 2159m
--------
* I couldn't get reduced vertical blanking (RVB) timing working, even
though it works on Linux.
* Using timings from Linux for standard 1920x1080 worked great. The
values are:

0300 #14850 #1920 #2200 #88 #44 #1080 #1125 #4 #9 (decimal)
0300 3A02 0780 0898 0058 002c 0438 0465 0004 0009 (hex)

* Patch file with:
2B7088: 03 01 24 3A 02 07 80 24 08 98 00 58 24 00 2C 04 38 24
04 65 00 04 23 00 09 00 03


Nicities
--------
* Open Monitors, set resolution, arrange, move menubar to external
monitor.
* Run little program that calls DMDisableDisplay() on internal LCD, then
I have one external monitor and can plug in keyboard and mouse and put
laptop out of the way and use it just like a desktop.
